iT邦幫忙

2022 iThome 鐵人賽

DAY 18
0

上篇講完 Message Event 基本介紹後,今天就來整理 Postback 的資訊並時做一個簡單的 postback 機器人來熟悉一下。

Postback event

postback event 是配合 postback action 的訊息事件,此種訊息不會被使用者看到,他在 postback action 被觸發時透過 API 將資訊內容(postback.data)傳送到 server 給程式或是系統做後續處理,因此可以利用它做使用者點擊按鈕後的後續動作或是蒐集資料等等。編編認為在設計服務上是很實用的功能₍₍◝(・'ω'・)◟⁾⁾。

屬性介紹

  • Common Properties(通用屬性)
  • type:postback
  • replyToken:可以回復這則訊息的 Reply Tocken
  • postback.data:資訊內容
  • postback.params:以下資訊的 json 檔
    • date-time selection action
      使用者透過 Datetime picker action 所記錄的 json,並由此做出處理。
    • rich menu switch action
      紀錄使用者選擇哪個 rich menu (可切換的圖文選單),並依此做出反應。
// Postback event for date-time selection action
{
    "destination": "xxxxxxxxxx",
    "events": [
        {
            "replyToken": "b60d432864f44d079f6d8efe86cf404b",
            "type": "postback",
            "mode": "active",
            "source": {
                "userId": "U91eeaf62d...",
                "type": "user"
            },
            "timestamp": 1513669370317,
            "webhookEventId": "01FZ74A0TDDPYRVKNK77XKC3ZR",
            "deliveryContext": {
                "isRedelivery": false
            },
            "postback": {
                "data": "storeId=12345",
                "params": {
                    "datetime": "2017-12-25T01:00"
                }
            }
        }
    ]
}
// Postback event for rich menu switch action
{
    "destination": "xxxxxxxxxx",
    "events": [
        {
            "replyToken": "b60d432864f44d079f6d8efe86cf404b",
            "type": "postback",
            "mode": "active",
            "source": {
                "userId": "U91eeaf62d...",
                "type": "user"
            },
            "timestamp": 1619754620404,
            "webhookEventId": "01FZ74A0TDDPYRVKNK77XKC3ZR",
            "deliveryContext": {
                "isRedelivery": false
            },
            "postback": {
                "data": "richmenu-changed-to-b",
                "params": {
                    "newRichMenuAliasId": "richmenu-alias-b",
                    "status": "SUCCESS"
                }
            }
        }
    ]
}

更詳細的屬性介紹可以看 官方文件 喔!

Postback 小練習

知道了 postback event 基本知識後就要開始動手練習了~
*記得要設定好 Webhook URL 喔(後面加 /callback)

首先先做一個基本的按鈕選單

根據選擇按鈕的回傳文字,會回傳文字訊息及圖片。
這裡我設定當使用者輸入「成員介紹」時會出現三個按鈕選擇。且將要執行的程式碼放到 fun.py 來寫,讓 view.py 保持乾淨。

  • view.py
from django.conf import settings
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
from django.views.decorators.csrf import csrf_exempt

from urllib.parse import parse_qsl
from linebot import LineBotApi, WebhookParser
from linebot.exceptions import InvalidSignatureError, LineBotApiError
from linebot.models import  *
from module import func

line_bot_api = LineBotApi(settings.LINE_CHANNEL_ACCESS_TOKEN)
parser = WebhookParser(settings.LINE_CHANNEL_SECRET)

@csrf_exempt
def callback(request):
    if request.method == 'POST':
        signature = request.META['HTTP_X_LINE_SIGNATURE']
        body = request.body.decode('utf-8')
        try:
            events = parser.parse(body, signature)
        except InvalidSignatureError:
            return HttpResponseForbidden()
        except LineBotApiError:
            return HttpResponseBadRequest()
        
        for event in events:
            if isinstance(event, MessageEvent):
                mtext = event.message.text
                if mtext == '成員介紹':
                    func.sendIntro(event)
                elif mtext == '第一隻喵':
                    func.sendcat01(event)
                elif mtext == '第二隻喵':
                    func.sendcat02(event)
                elif mtext == '第三隻喵':
                    func.sendcat03(event)
  • fun.py
    linebot.models 我想要直接 import 全部,因我打「from linebot.models import *」
from django.conf import settings
from linebot import LineBotApi
from linebot.models import *

line_bot_api = LineBotApi(settings.LINE_CHANNEL_ACCESS_TOKEN)


def sendIntro(event):
    try:
        message = TemplateSendMessage(
            alt_text='Buttons template',
            template = ButtonsTemplate(
                thumbnail_image_url="https://images.pexels.com/photos/160755/kittens-cats-foster-playing-160755.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
                title='成員介紹',
                text='請選擇',
                actions=[
                    MessageTemplateAction(
                        label='第一隻喵',
                        text='第一隻喵'
                        ),
                    MessageTemplateAction(
                        label='第二隻喵',
                        text='第二隻喵'
                        ),
                    MessageTemplateAction(
                        label='第三隻喵',
                        text='第三隻喵'
                        
                    )
                ]
            )
            
        )
        line_bot_api.reply_message(event.reply_token,message)
        
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='失敗'))
        
def sendcat01(event):
    try:
        message_A = []
        message_A.append(TextSendMessage(text="我是喵仔"))
        message_A.append(ImageSendMessage(
            original_content_url="https://images.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
            preview_image_url="https://images.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
            ))
        line_bot_api.reply_message(event.reply_token,message_A)
        
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='失敗'))
        
def sendcat02(event):
    try:
        message_A = []
        message_A.append(TextSendMessage(text="我是毛毛"))
        message_A.append(ImageSendMessage(
            original_content_url="https://images.pexels.com/photos/257532/pexels-photo-257532.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
            preview_image_url="https://images.pexels.com/photos/257532/pexels-photo-257532.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
            ))
        line_bot_api.reply_message(event.reply_token,message_A)
        
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='失敗'))

def sendcat03(event):
    try:
        message_A = []
        message_A.append(TextSendMessage(text="我是嚕嚕"))
        message_A.append(ImageSendMessage(
            original_content_url="https://images.pexels.com/photos/1404819/pexels-photo-1404819.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
            preview_image_url="https://images.pexels.com/photos/1404819/pexels-photo-1404819.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
            ))
        line_bot_api.reply_message(event.reply_token,message_A)
        
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='失敗'))

手機上樣子!

Postback 設定

現在將原本透過判定使用者輸入的文字做反應的做改為用 postback 呼叫。

  • view.py
    將判斷使用者輸入「第一隻喵」、「第二隻喵」、「第三隻喵」的判斷刪掉,並加上當接收到 postback 訊息時要做的動作。
                for event in events:
            if isinstance(event, MessageEvent):
                mtext = event.message.text
                
                if mtext == '成員介紹':
                    func.sendIntro(event)
    
                    
        if isinstance(event, PostbackEvent):
            backdata = dict(parse_qsl(event.postback.data))
            if backdata.get('action') == '第一隻喵':
                func.sendBack_cat01(event, backdata)
            elif backdata.get('action') == '第二隻喵':
                func.sendBack_cat02(event,backdata)
            elif backdata.get('action') == '第三隻喵':
                func.sendBack_cat03(event,backdata)
  • fun.py
    將 MessageTemplateAction 換成 PostbackTemplateAction ,這個 model 有 data ,可以將要傳到 server 的資訊寫在此處且使用者看不到。
def sendIntro(event):
    try:
        message = TemplateSendMessage(
            alt_text='Buttons template',
            template = ButtonsTemplate(
                thumbnail_image_url="https://images.pexels.com/photos/160755/kittens-cats-foster-playing-160755.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
                title='成員介紹',
                text='請選擇',
                actions=[
                    PostbackTemplateAction(
                        label='第一隻喵',
                        text='第一隻喵_postback',
                        data='action=第一隻喵'
                    ),
                    PostbackTemplateAction(
                        label='第二隻喵_postback',
                        text='第二隻喵_postback',
                        data='action=第二隻喵'
                    ),
                    PostbackTemplateAction(
                        label='第三隻喵_postback',
                        
                        data='action=第三隻喵'
                    )
                ]
            )
            
        )
        line_bot_api.reply_message(event.reply_token,message)
        
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='失敗'))

記得 fuc 後面參數有加因此此處要記得修改名稱~

def sendBack_cat01(event, backdata):
    try:
        message_A = []
        message_A.append(TextSendMessage(text="我是喵仔"))
        message_A.append(ImageSendMessage(
            original_content_url="https://images.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1.png",
            preview_image_url="https://images.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1.png"
            ))
        line_bot_api.reply_message(event.reply_token,message_A)
        
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='失敗'))
        
def sendBack_cat02(event,backdata):
    try:
        message_A = []
        message_A.append(TextSendMessage(text="我是毛毛"))
        message_A.append(ImageSendMessage(
            original_content_url="https://images.pexels.com/photos/257532/pexels-photo-257532.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
            preview_image_url="https://images.pexels.com/photos/257532/pexels-photo-257532.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
            ))
        line_bot_api.reply_message(event.reply_token,message_A)
        
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='失敗'))

def sendBack_cat03(event,backdata):
    try:
        message_A = []
        message_A.append(TextSendMessage(text="我是嚕嚕"))
        message_A.append(ImageSendMessage(
            original_content_url="https://images.pexels.com/photos/1404819/pexels-photo-1404819.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
            preview_image_url="https://images.pexels.com/photos/1404819/pexels-photo-1404819.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1"
            ))
        line_bot_api.reply_message(event.reply_token,message_A)
        
    except:
        line_bot_api.reply_message(event.reply_token,TextSendMessage(text='失敗'))

這樣就完成了簡單的練習喔(❀╹◡╹)!


小結尾:
在第一部份中跟著鐵人賽的腳步,學習與複習LINE Bot的各種基礎功能介紹,對編編們算是初學者來說非常的獲益良多,幸好擁有參加鐵人賽的機會讓編編們學習用Python完成Line Bot的服務,雖然已學習完基本功能,但也不可以停下腳步,有更深入更實用的小技巧以及實作,對未來的應用或是比賽甚至職場上,才真正可以派上用場,接下來幾天踏上實作之旅一起動手試試看吧(๑•̀ㅂ•́)و✧


上一篇
DAY 17 Line 訊息的介紹
下一篇
DAY 19 Python基本語法(上篇)
系列文
30天建構出一個簡單 LineBot 機器人30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
arguskao
iT邦新手 4 級 ‧ 2023-10-09 18:00:13

寫得真好!

我要留言

立即登入留言